﻿using System;
using GeoAPI.Geometries;

namespace GeoAPI.IO
{
	[CLSCompliant(false)]
	public struct GeometryType
	{
		public GeometryType(uint geometryType)
		{
			this._geometrytype = geometryType;
		}

		public GeometryType(IGeometry geometry, Ordinates ordinates)
		{
			this = new GeometryType(geometry.OgcGeometryType, ordinates, geometry.SRID >= 0);
		}

		public GeometryType(OgcGeometryType ogcGeometryType)
		{
			this = new GeometryType(ogcGeometryType, Ordinates.XY, false);
		}

		public GeometryType(OgcGeometryType ogcGeometryType, bool hasSrid)
		{
			this = new GeometryType(ogcGeometryType, Ordinates.XY, hasSrid);
		}

		public GeometryType(OgcGeometryType ogcGeometryType, Ordinates ordinates, bool hasSrid)
		{
			this._geometrytype = (uint)ogcGeometryType;
			if ((ordinates & Ordinates.Z) != Ordinates.None)
			{
				this.HasWkbZ = true;
				this.HasEwkbM = true;
			}
			if ((ordinates & Ordinates.M) != Ordinates.None)
			{
				this.HasWkbZ = true;
				this.HasEwkbM = true;
			}
			this.HasEwkbSrid = hasSrid;
		}

		public OgcGeometryType BaseGeometryType
		{
			get
			{
				uint num = this._geometrytype & 16777215u;
				if (num > 2000u)
				{
					num -= 2000u;
				}
				if (num > 1000u)
				{
					num -= 1000u;
				}
				return (OgcGeometryType)num;
			}
			set
			{
				uint num = this._geometrytype & 234881024u;
				uint num2 = (uint)value;
				if (this.HasWkbZ)
				{
					num2 += 1000u;
				}
				if (this.HasWkbM)
				{
					num2 += 2000u;
				}
				this._geometrytype = (num | num2);
			}
		}

		public int WkbGeometryType
		{
			get
			{
				return (int)(this._geometrytype & 33554431u);
			}
		}

		public int EwkbWkbGeometryType
		{
			get
			{
				return (int)(this.BaseGeometryType | (OgcGeometryType)(this._geometrytype & 4261412864u));
			}
		}

		public bool HasZ
		{
			get
			{
				return this.HasWkbZ | this.HasEwkbZ;
			}
		}

		public bool HasM
		{
			get
			{
				return this.HasWkbM | this.HasEwkbM;
			}
		}

		public bool HasSrid
		{
			get
			{
				return this.HasEwkbSrid;
			}
		}

		public bool HasWkbZ
		{
			get
			{
				return this._geometrytype / 1000u == 1u;
			}
			set
			{
				if (value == this.HasWkbZ)
				{
					return;
				}
				if (this.HasWkbZ)
				{
					this._geometrytype -= 1000u;
					return;
				}
				this._geometrytype += 1000u;
			}
		}

		public bool HasWkbM
		{
			get
			{
				return this._geometrytype / 2000u == 2u;
			}
			set
			{
				if (value == this.HasWkbM)
				{
					return;
				}
				if (this.HasWkbM)
				{
					this._geometrytype -= 2000u;
					return;
				}
				this._geometrytype += 2000u;
			}
		}

		public bool HasEwkbZ
		{
			get
			{
				return (this._geometrytype & 134217728u) == 134217728u;
			}
			set
			{
				uint geometrytype = this._geometrytype & 4160749567u;
				if (value)
				{
					geometrytype = (this._geometrytype | 134217728u);
				}
				this._geometrytype = geometrytype;
			}
		}

		public bool HasEwkbM
		{
			get
			{
				return (this._geometrytype & 67108864u) == 67108864u;
			}
			set
			{
				uint geometrytype = this._geometrytype & 4227858431u;
				if (value)
				{
					geometrytype = (this._geometrytype | 67108864u);
				}
				this._geometrytype = geometrytype;
			}
		}

		public bool HasEwkbSrid
		{
			get
			{
				return (this._geometrytype & 33554432u) == 33554432u;
			}
			set
			{
				uint geometrytype = this._geometrytype & 4261412863u;
				if (value)
				{
					geometrytype = (this._geometrytype | 33554432u);
				}
				this._geometrytype = geometrytype;
			}
		}

		private const uint EwkbZFlag = 134217728u;

		private const uint EwkbMFlag = 67108864u;

		private const uint EwkbSridFlag = 33554432u;

		private const uint EwkbFlags = 234881024u;

		private uint _geometrytype;
	}
}
